use std::time::Duration;

use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
use crate::components::enums::{NetworkCommand, NetworkEvent};

// TCP 异步任务
pub async fn tcp_task(
    mut cmd_rx: UnboundedReceiver<NetworkCommand>,
    event_tx: UnboundedSender<NetworkEvent>,
) {
    let mut stream: Option<TcpStream> = None;
    let mut buf = vec![0; 4096]; // 复用缓冲区

    loop {
        // 使用 tokio::select! 宏来同时等待来自 UI 的命令和来自网络的数据
        tokio::select! {
            // 1. 处理来自 UI 线程的命令
            Some(command) = cmd_rx.recv() => {
                match command {
                    NetworkCommand::Connect(addr) => {
                        // 如果已存在连接，先断开
                        if let Some(mut s) = stream.take() {
                            let _ = s.shutdown().await;
                        }
                        // 【关键修改】使用5秒超时来包裹连接操作
                        match tokio::time::timeout(
                            Duration::from_secs(5),
                            TcpStream::connect(&addr)
                        ).await {
                        // 超时
                        Err(_) => {
                            let _ = event_tx.send(NetworkEvent::Error("Connection timed out".to_string()));
                        }
                        // 未超时，处理内部的连接结果
                        Ok(Ok(s)) => {
                            stream = Some(s);
                            let _ = event_tx.send(NetworkEvent::Connected);
                        }
                        Ok(Err(e)) => {
                            let _ = event_tx.send(NetworkEvent::Error(e.to_string()));
                            }
                        }
                    }
                    NetworkCommand::Send(data) => {
                        if let Some(s) = stream.as_mut() {
                            if let Err(e) = s.write_all(&data).await {
                                let _ = event_tx.send(NetworkEvent::Error(e.to_string()));
                            }
                        }
                    }
                    NetworkCommand::Disconnect => {
                        if let Some(mut s) = stream.take() {
                            let _ = s.shutdown().await;
                        }
                        // 无论如何都发送 Disconnected 事件
                        let _ = event_tx.send(NetworkEvent::Disconnected);
                    }
                }
            },

            // 2. 如果已连接，则尝试从网络读取数据
            // 这个分支只有在 stream.is_some() 时才会被 select! 启用
            result = async {
                stream.as_mut().unwrap().read(&mut buf).await
            }, if stream.is_some() => {
                match result {
                    Ok(0) => {
                        // 对等方关闭了连接
                        stream = None;
                        let _ = event_tx.send(NetworkEvent::Disconnected);
                    },
                    Ok(n) => {
                        // 成功读取到数据
                        let _ = event_tx.send(NetworkEvent::DataReceived(buf[..n].to_vec()));
                    },
                    Err(e) => {
                        // 发生读取错误
                        stream = None;
                        let _ = event_tx.send(NetworkEvent::Error(e.to_string()));
                        let _ = event_tx.send(NetworkEvent::Disconnected);
                    }
                }
            }
        }
    }
}
